package com.quantum.core.components
{
	import com.quantum.core.events.DockingEvent;
	import com.quantum.core.layout.BorderLayout;
	import com.quantum.core.layout.BorderLayoutPosition;
	import com.quantum.core.managers.PerspectiveManager;
	import com.quantum.core.managers.ViewManager;

	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	import mx.binding.utils.BindingUtils;
	import mx.containers.Canvas;
	import mx.containers.HBox;
	import mx.containers.TabNavigator;
	import mx.controls.Button;
	import mx.core.EdgeMetrics;
	import mx.core.ScrollPolicy;
	import mx.events.DragEvent;
	import mx.events.IndexChangedEvent;
	import mx.events.ItemClickEvent;
	import mx.managers.DragManager;
	import mx.managers.PopUpManager;
	import mx.skins.ProgrammaticSkin;

	public class ViewWindow extends TabNavigator implements DockingWindow
	{
		public static const MINIMIZED_HEIGHT:Number=22;
		public static const WINDOW_STATE_DEFAULT:Number=-1;
		public static const WINDOW_STATE_MINIMIZED:Number=0;
		public static const WINDOW_STATE_MAXIMIZED:Number=1;

		public var windowState:Number; // Corresponds to one of the WINDOW_STATE variables.
		public var index:Number; // Index within the layout.

		private var _dropEnabled:Boolean=true;

		private var _dragEnabled:Boolean=true;

		public var borderLayout:String=BorderLayout.CENTER;

		public var borderLayoutPosition:BorderLayoutPosition;

		/** child component */
		protected var titleBar:ViewWindowBar;

		protected var canvas:Canvas;

		private var _originalWidth:Number=-1;

		public function get originalWidth():Number
		{
			return _originalWidth;
		}

		public function set originalWidth(value:Number):void
		{
			_originalWidth=value;
		}

		private var _originalHeight:Number=-1;

		public function get originalHeight():Number
		{
			return _originalHeight;
		}

		public function set originalHeight(value:Number):void
		{
			_originalHeight=value;
		}

		private var _originalParent:DisplayObjectContainer=null;

		public function get originalParent():DisplayObjectContainer
		{
			return _originalParent;
		}

		public function set originalParent(value:DisplayObjectContainer):void
		{
			_originalParent=value;
		}

		public var originalX:Number;
		public var originalY:Number;
		public var targetWidth:Number=-1;
		public var targetHeight:Number=-1;
		public var actived:Boolean=false;

		protected var minimizeButton:Button;

		protected var maximizeButton:Button;

		protected var viewActionBar:HBox;

		protected var dockProxy:Canvas;

		private var _showControls:Boolean;
		private var _showControlsChanged:Boolean;

		private var _maximize:Boolean;
		private var _maximizeChanged:Boolean;

		public function ViewWindow()
		{
			super();

			windowState=WINDOW_STATE_DEFAULT;
			horizontalScrollPolicy="off";

			addEventListener(DockingEvent.CLOSED, onViewClosed);

			addEventListener(DragEvent.DRAG_OVER, onDragOver);
			addEventListener(DragEvent.DRAG_ENTER, onDragEnter);
			addEventListener(DragEvent.DRAG_EXIT, onDragExit);
			addEventListener(DragEvent.DRAG_DROP, onDragDrop);

			addEventListener(IndexChangedEvent.CHANGE, tabChangedEvent);
			addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);

			percentWidth=percentHeight=100;
			styleName="viewWindow";

			doubleClickEnabled=true;
			focusEnabled=true;

			BindingUtils.bindSetter(onAcitiveViewChange, ViewManager.getInstance(), "activeViewWindow");
		}

		public function onAcitiveViewChange(value:String):void
		{
			if (!value)
			{
				return;
			}
			actived=value == uid;
			if (actived)
			{
				setStyle("backgroundColor", "0x9ABAE9");
			}
			else
			{
				setStyle("backgroundColor", "0xF0F0F0");
			}
			if (tabBar)
			{
				for each (var tab:Button in tabBar.getChildren())
				{
					tab.styleChanged("selectedUpSkin");
				}
			}
		}

		public function clearOriginalSize():void
		{
			originalParent=null;
			originalWidth=-1;
			originalHeight=-1;
		}

		public function saveOriginalContext():void
		{
			originalParent=parent;
			originalWidth=isNaN(percentWidth) ? width * 100 / parent.width : percentWidth;
			originalHeight=isNaN(percentHeight) ? height * 100 / parent.height : percentHeight;
			originalX=x;
			originalY=y;
		}

		public function restoreOriginalContext():void
		{
			if (originalParent && !originalParent.contains(this))
			{
				originalParent.addChild(this);
			}
			percentWidth=originalWidth;
			percentHeight=originalHeight;
			x=originalX;
			y=originalY;
		}

		public function get dropEnabled():Boolean
		{
			if (tabBar)
			{
				return (tabBar as ViewTabBar).dropEnabled;
			}
			else
			{
				return _dropEnabled;
			}
		}

		public function set dropEnabled(value:Boolean):void
		{
			_dropEnabled=value;

			if (tabBar)
			{
				(tabBar as ViewTabBar).dropEnabled=value;
			}
		}

		override protected function createChildren():void
		{
			if (!tabBar)
			{
				// We're using our custom ViewTabBar class instead of TabBar
				tabBar=new ViewTabBar();
				tabBar.name="tabBar";
				tabBar.focusEnabled=false;
				tabBar.styleName=this;
				(tabBar as ViewTabBar).dragEnabled=_dragEnabled;
				(tabBar as ViewTabBar).dropEnabled=_dropEnabled;

				tabBar.setStyle("borderStyle", "none");
				tabBar.setStyle("paddingTop", 0);
				tabBar.setStyle("paddingLeft", 0);
				tabBar.setStyle("paddingBottom", 0);
				tabBar.setStyle("paddingRight", 3);

				(tabBar as ViewTabBar).closeButtonVisiblePolicy=ViewTab.CLOSE_BUTTON_VISIBLE_ROLLOVER;
			}
			super.createChildren();

			if (!titleBar)
			{
				titleBar=new ViewWindowBar();
				titleBar.horizontalScrollPolicy=ScrollPolicy.OFF;
				rawChildren.addChild(titleBar);
				titleBar.addEventListener(MouseEvent.DOUBLE_CLICK, onClickMaximizeRestoreButton);
				titleBar.addEventListener(MouseEvent.CLICK, onClickTitleBar);
			}

			if (null == canvas)
			{
				canvas=new Canvas();
				canvas.styleName=this;
				canvas.setStyle("borderStyle", "none");
				canvas.setStyle("backgroundAlpha", 0);
				canvas.setStyle("paddingTop", 0);
				canvas.setStyle("paddingBottom", 0);
				canvas.horizontalScrollPolicy=ScrollPolicy.OFF;
				canvas.verticalScrollPolicy=ScrollPolicy.OFF;
				canvas.addChild(tabBar);
				titleBar.addChild(canvas);
			}

			if (!minimizeButton)
			{
				minimizeButton=new Button();
				minimizeButton.width=minimizeButton.height=18;
				minimizeButton.styleName="minimizeButton";
				minimizeButton.toolTip="最小化";
				minimizeButton.addEventListener(MouseEvent.CLICK, onMinimize);
				titleBar.addChild(minimizeButton);
			}

			if (!maximizeButton)
			{
				maximizeButton=new Button();
				maximizeButton.width=maximizeButton.height=18;
				maximizeButton.styleName="maximizeButton";
				maximizeButton.toolTip="最大化";
				maximizeButton.addEventListener(MouseEvent.CLICK, onClickMaximizeRestoreButton);
				titleBar.addChild(maximizeButton);
			}

			tabBar.addEventListener(ViewTabBar.TABS_REORDERED, tabsReordered);

			titleBar.doubleClickEnabled=true;
			titleBar.addEventListener(MouseEvent.DOUBLE_CLICK, onClickMaximizeRestoreButton);


			if (!dockProxy)
			{
				dockProxy=new Canvas();

				dockProxy.setStyle("backgroundAlpha", 0.4);
				dockProxy.setStyle("backgroundColor", 0xD4D0C8);
				dockProxy.setStyle("borderStyle", "solid");
				dockProxy.setStyle("borderThickness", 3);
				dockProxy.setStyle("borderColor", 0x58B299);

				dockProxy.visible=false;
				rawChildren.addChild(dockProxy);
			}

			invalidateSize();
		}

		private function onMouseDown(event:Event):void
		{
			ViewManager.getInstance().activeViewWindow=uid;
		}

		public function minimize():void
		{
			windowState=WINDOW_STATE_MINIMIZED;
			showControls=false;
		}

		public function set showControls(value:Boolean):void
		{
			_showControls=value;
			_showControlsChanged=true;
			invalidateProperties();
		}

		public function get closeButtonVisiblePolicy():String
		{
			return (tabBar as ViewTabBar).closeButtonVisiblePolicy;
		}

		public function set closeButtonVisiblePolicy(value:String):void
		{
			var old:String=(tabBar as ViewTabBar).closeButtonVisiblePolicy;
			(tabBar as ViewTabBar).closeButtonVisiblePolicy=value;
			if (old != value)
			{
				invalidateDisplayList();
			}
		}

		private function tabsReordered(event:Event):void
		{
		}

		private var forcedTabWidth:Number=-1;

		private var originalTabWidthStyle:Number=-1;

		private var _minTabWidth:Number=60;


		override protected function commitProperties():void
		{
			super.commitProperties();

			if (_showControlsChanged)
			{
				includeInLayout=visible=_showControls;
				_showControlsChanged=false;
			}
		}

		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);

			minimizeButton.includeInLayout=maximizeButton.includeInLayout=true;
			var vm:EdgeMetrics=viewMetrics;
			var w:Number=unscaledWidth - vm.left - vm.right;

			var th:Number=tabBarHeight;
			var pw:Number=tabBar.getExplicitOrMeasuredWidth();

			var tabBarSpace:Number=w;

			tabBarSpace-=maximizeButton.width;
			tabBarSpace-=minimizeButton.width;

			if (pw > tabBarSpace)
			{
				var numTabs:Number=tabBar.numChildren;
				var tabSizeNeeded:Number=Math.max((tabBarSpace - getStyle("horizontalGap") * (numTabs - 1)) / numTabs, _minTabWidth);

				if (forcedTabWidth != tabSizeNeeded)
				{
					if (originalTabWidthStyle == -1)
					{
						originalTabWidthStyle=getStyle("tabWidth");
					}

					forcedTabWidth=tabSizeNeeded;
					setStyle("tabWidth", forcedTabWidth);
					callLater(invalidateDisplayList);
					return;
				}
			}
			else
			{
				if (forcedTabWidth == -1 && getStyle("tabWidth") != originalTabWidthStyle && originalTabWidthStyle != -1)
				{
					if (getStyle("tabWidth") != undefined)
					{
						if (isNaN(originalTabWidthStyle))
						{
							clearStyle("tabWidth");
							tabBar.invalidateSize();
							tabBar.invalidateDisplayList();
						}
						else
						{
							setStyle("tabWidth", originalTabWidthStyle);
						}

						callLater(invalidateDisplayList);
					}
				}
				forcedTabWidth=-1;
			}

			if (forcedTabWidth != -1)
			{
				pw=(forcedTabWidth * tabBar.numChildren) + (getStyle("horizontalGap") * (tabBar.numChildren - 1));
			}
			var canvasWidth:Number=unscaledWidth;
			canvasWidth-=maximizeButton.width;
			canvasWidth-=minimizeButton.width;
			canvasWidth-=3;
			canvas.width=canvasWidth;
			canvas.height=th;

			if (pw <= canvasWidth)
			{
				canvas.horizontalScrollPosition=0;
			}

			tabBar.move(0, 0);
			tabBar.setActualSize(pw, th);

			titleBar.move(0, 0);
			titleBar.setActualSize(unscaledWidth, th);

			if (pw < canvasWidth)
			{
				switch (getStyle("horizontalAlign"))
				{
					case "left":
						tabBar.move(0, tabBar.y);
						break;
					case "right":
						tabBar.move(unscaledWidth - tabBar.width, tabBar.y);
						break;
					case "center":
						tabBar.move((unscaledWidth - tabBar.width) / 2, tabBar.y);
				}
			}
		}


		/**
		 * tabBarHeight is the same as the same funtion in TabNavigator, but the
		 * one in TabNavigator was private, so we had to reproduce it here.
		 */
		protected function get tabBarHeight():Number
		{
			var tabHeight:Number=getStyle("tabHeight");

			if (isNaN(tabHeight))
				tabHeight=tabBar.getExplicitOrMeasuredHeight();

			return tabHeight;
		}

		/**
		 * The tabs can be changed any number of ways (via drop-down menu, via AS, etc)
		 * so this listener function will make sure that the tab that gets selected is
		 * visible.
		 */
		private function tabChangedEvent(event:IndexChangedEvent):void
		{
			//callLater(ensureTabIsVisible);
			if (actived)
			{
				(selectedChild as DockingView).actived=true;
			}
		}

		private function handleTabMouseOut(event:MouseEvent):void
		{
			if (getStageWindow().docking)
			{
				PopUpManager.removePopUp(dockProxy);
			}
		}

		private function handleTabMouseUp(event:MouseEvent):void
		{
			if (getStageWindow().docking && null != getStageWindow().dockView)
			{

				var view:DisplayObject=getStageWindow().dockView as DisplayObject

				var oldIndex:int=view.parent.getChildIndex(view);
				var newIndex:int=0;

				ViewWindow(view.parent).removeChildAt(oldIndex);
				addChildAt(view, newIndex);

				//validate the visible items for the tab bar.
				//extended_TabBar(tabBar).validateVisibleTabs();

				getStageWindow().docking=false;
				getStageWindow().dockView=null;
				PopUpManager.removePopUp(dockProxy);
			}
		}

		private function handleTabMouseMove(event:MouseEvent):void
		{

		}

		private function handleTabMouseDown(event:MouseEvent):void
		{

		}

		private function getRealRect():Rectangle
		{
			var rectangle:Rectangle=new Rectangle();
			rectangle.width=width;
			rectangle.height=height;

			var point:Point=new Point();
			point.x=0;
			point.y=0; //- viewMetrics.top;
			point=localToGlobal(point);
			rectangle.x=point.x;
			rectangle.y=point.y;
			rectangle.y=point.y;
			return rectangle;
		}

		private function handleDragEnter(event:DragEvent):void
		{
			if (event.dragSource.hasFormat(ViewTab.FORMAT))
			{
				var dropTarget:ViewWindow=ViewWindow(event.currentTarget);
				DragManager.acceptDragDrop(dropTarget);
			}
		}

		/**
		 * draw indicator to show user where the tab
		 * will be inserted
		 **/
		private function onDragOver(event:DragEvent):void
		{
			if (event.dragSource.hasFormat(ViewTab.FORMAT))
			{

				borderLayout=BorderLayout.CENTER;

				if (getStageWindow().docking)
				{

					var rectangle:Rectangle=getRealRect();
					var x:int=0;
					var y:int=0;

					var dockView:ViewTab=event.dragInitiator as ViewTab;
					var viewWindow:ViewWindow=dockView.getViewWindow();

					if (this == viewWindow && 1 == viewWindow.getChildren().length)
					{

					}
					else
					{
						if (event.localX < rectangle.width / 4)
						{
							borderLayout=BorderLayout.WEST;
							rectangle.width/=2;
						}
						else if (event.localX > rectangle.width * 3 / 4)
						{
							borderLayout=BorderLayout.EAST;
							x=rectangle.width / 2;
							rectangle.width/=2;
						}
						else
						{
							if (event.localY < rectangle.height / 4)
							{
								borderLayout=BorderLayout.NORTH;
								rectangle.height/=2;
							}
							else if (event.localY > rectangle.height * 3 / 4)
							{
								borderLayout=BorderLayout.SOUTH;
								y+=rectangle.height / 2;
								rectangle.height/=2;
							}
						}
					}

					dockProxy.width=rectangle.width;
					dockProxy.height=rectangle.height;
					dockProxy.move(x, y);

					if (!dockProxy.visible)
					{
						dockProxy.visible=true;
					}
				}
			}
		}

		private function onDragEnter(event:DragEvent):void
		{
			if (event.dragSource.hasFormat(ViewTab.FORMAT))
			{
				var dropTarget:ViewWindow=ViewWindow(event.currentTarget);
				DragManager.acceptDragDrop(dropTarget);

				event.stopPropagation();
				event.preventDefault();

				var rectangle:Rectangle=getRealRect();

				dockProxy.width=rectangle.width;
				dockProxy.height=rectangle.height;
				dockProxy.move(0, 0);
				dockProxy.visible=true;

				getStageWindow().docking=true;
				getStageWindow().dockView=event.target as DisplayObject;
			}
		}

		private function onViewDocked(event:DockingEvent):void
		{
			if (numChildren == 0)
			{
				parent.removeChild(this);
			}
		}

		/**
		 * clean up the drag drop indicator
		 **/
		private function onDragExit(event:DragEvent):void
		{
			dockProxy.visible=false;
		}

		private function onDragDrop(event:DragEvent):void
		{
			dockProxy.visible=false;

			var dockEvent:DockingEvent=new DockingEvent(DockingEvent.DOCKED);
			dockEvent.viewTab=ViewTab(event.dragInitiator);
			dockEvent.viewWindow=this;

			dispatchEvent(dockEvent);
		}


		/**
		 * when dragged (even between navigators) if the format is correct
		 * move the tab to the new parent and location if the target is the
		 * navigator then the new tab is inserted at location 0.
		 **/
		private function handleTabDragDrop(event:DragEvent):void
		{
		}

		private function onDock(event:ItemClickEvent):void
		{
			event.stopPropagation();
			event.preventDefault();

			var rectangle:Rectangle=getRealRect();

			dockProxy.width=rectangle.width;
			dockProxy.height=rectangle.height;
			dockProxy.move(rectangle.x, rectangle.y);
			getStageWindow().docking=true;
			getStageWindow().dockView=event.target as DisplayObject;
		}


		private function onMinimize(event:MouseEvent):void
		{
			event.stopImmediatePropagation();
			if (windowState == WINDOW_STATE_DEFAULT)
			{
				saveOriginalContext();
			}
			dispatchEvent(new DockingEvent(DockingEvent.MINIMIZE));
			minimize();
		}

		public function fireRestore():void
		{
			showControls=true;
			maximizeButton.styleName="maximizeButton";
			maximizeButton.toolTip="最大化";
			windowState=WINDOW_STATE_DEFAULT;
			dispatchEvent(new DockingEvent(DockingEvent.RESTORE));
		}

		private function onClickMaximizeRestoreButton(event:MouseEvent=null):void
		{
			showControls=true;
			if (windowState == WINDOW_STATE_DEFAULT)
			{
				saveOriginalContext();
				dispatchEvent(new DockingEvent(DockingEvent.MAXIMIZE));
				// Call after the event is dispatched so the old state is still available.
				maximize();
				maximizeButton.styleName="restoreButton";
				maximizeButton.toolTip="恢复";
			}
			else
			{
				restoreOriginalContext();

				dispatchEvent(new DockingEvent(DockingEvent.RESTORE));
				// Set the state after the event is dispatched so the old state is still available.
				windowState=WINDOW_STATE_DEFAULT;
			}
		}

		public function maximize():void
		{
			windowState=WINDOW_STATE_MAXIMIZED;
			_maximize=true;
			_maximizeChanged=true;
		}

		private function onClickTitleBar(event:MouseEvent):void
		{
			if (windowState == WINDOW_STATE_MINIMIZED)
			{
				// Add the bottom border back in case we were minimized.
				onClickMaximizeRestoreButton();
			}
		}

		private function onViewClosed(event:ItemClickEvent):void
		{
			event.stopPropagation();
			event.preventDefault();

			var view:DockingView=getChildAt(event.index) as DockingView;
			if (view && view.closable())
			{
				ViewManager.getInstance().removeViewInstance(view, PerspectiveManager.getInstance().activePerspective);
				var object:DisplayObject=removeChildAt(event.index);
				object=null;
			}
		}

		override public function removeChildAt(index:int):DisplayObject
		{
			var object:DisplayObject=super.removeChildAt(index);
			var event:DockingEvent=new DockingEvent(DockingEvent.REMOVED, true, true);
			event.view=object as DockingView;
			event.viewWindow=this;
			dispatchEvent(event);
			return object;
		}

		override public function drawFocus(isFocused:Boolean):void
		{
			super.drawFocus(isFocused);
		}

		private function getStageWindow():StageWindow
		{
			var object:DisplayObject=this;
			while (!(object is StageWindow))
			{
				object=object.parent;
			}
			return StageWindow(object);
		}

		public function get dragEnabled():Boolean
		{
			if (tabBar)
			{
				return (tabBar as ViewTabBar).dragEnabled;
			}
			else
			{
				return _dragEnabled;
			}
		}

		public function set dragEnabled(value:Boolean):void
		{
			_dragEnabled=value;

			if (tabBar)
			{
				(tabBar as ViewTabBar).dragEnabled=value;
			}
		}


		public function doClose():void
		{

		}

		public function doMinimize():void
		{

		}

		public function doMaximize():void
		{

		}

		public function doRestore():void
		{

		}

		public function doDetached():void
		{

		}

		public function doDock():void
		{

		}
	}
}